S2 | Señales - Ejercicios¶

Objetivo: Comprender los conceptos de señales, sus representaciones y transformaciones.


Bibliotecas¶

In [21]:
import numpy as np
import plotly.graph_objects as go
import plotly.offline
from plotly.subplots import make_subplots
import sympy as sp
from sympy import symbols, exp, sin, cos, pi, I, Heaviside, lambdify, integrate, sqrt
from IPython.display import display, HTML

##Workaround para mostrar fórmulas de LaTeX en Plotly
plotly.offline.init_notebook_mode()
display(HTML(
    '<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_SVG"></script>'
))

Parte I: Señales básicas¶

Pregunta 1: Representación de señales discretas y continuas¶

a) Defina una señal discreta con los valores x = [1, 2, 3] en los índices n = [-1, 0, 1]. Grafique usando stem plot.

b) Defina simbólicamente la señal continua $x_1(t) = t^2$ y grafíquela.

In [ ]:
# Solución:
# a) Señal discreta
x = np.array([1,2,3])
n = np.array([-1,0,1])

fig = go.Figure()
fig.add_trace(go.Scatter(
    x=n, y=x,
    mode='markers',
    marker=dict(size=10, color='lime'),
    name='x[n]'
))

for ni, xi in zip(n,x):
    fig.add_shape(
        type='line',
        x0=ni, y0=0, x1=ni, y1=xi,
        line=dict(color='lime', width=2)
    )
fig.update_layout(
    title='Señal discreta con stem plot',
    xaxis_title='n',
    yaxis_title='x[n]',
    template='plotly_dark',
    showlegend=False
)

fig.show()

# b) Señal continua simbólica
t = symbols('t')
x1 = t**2

xfun = lambdify(t, x1, 'numpy')

tvals = np.linspace(-5,5,1000)
xvals = xfun(tvals)

fig = go.Figure()

fig.add_trace(go.Scatter(
    x=tvals, y=xvals, 
    mode='lines',
    name=f'x(t) = {x1}',
    line=dict(color='lime', width=2)
    ))

fig.update_layout(
    title='Señal continua y definida simbólicamente',
    xaxis_title='t',
    yaxis_title='x(t)',
    template='plotly_dark'
    )

fig.show()

# c) Graficación de ambas

Pregunta 2: Señales exponenciales¶

a) Defina y grafique las siguientes señales exponenciales en el intervalo $[-2, 5]$:

  • $x(t) = 3e^{0.4t}$ (crecimiento exponencial)
  • $y(t) = 2e^{-0.9t}$ (decaimiento exponencial)

b) Compare ambas señales en la misma gráfica con leyenda.

In [42]:
# Solución:
# a) Definir x(t) y y(t)
t = symbols('t')
x = 3*exp(0.4*t)
y = 2*exp(-0.9*t)

tvals = np.linspace(-4,8,1000)

xfun = lambdify(t, x, 'numpy')
yfun = lambdify(t, y, 'numpy')

xvals = xfun(tvals)
yvals = yfun(tvals)
# b) Graficar ambas señales

fig = go.Figure()

fig.add_trace(go.Scatter(
    x=tvals, y=xvals,
    mode='lines',
    line=dict(color='lime',width=2),
    name=f'x(t) = {x}'
    ))

fig.add_trace(go.Scatter(
    x=tvals, y=yvals,
    mode='lines',
    line=dict(color='cyan', width=2, dash='dash'),
    name=f'y(t) = {y}'
    ))

fig.update_layout(title='Exponencial creciente y decreciente',
    xaxis_title='t',
    yaxis_title='Exponenciales',
    template='plotly_dark',
    hovermode='x unified'
    )

fig.show()

Pregunta 3: Comparación señal continua vs discreta¶

a) Defina la señal contínua $y(t) = \cos(t)$ y grafíquela en el intervalo $[0, 10]$.

b) Evalúe la misma función coseno en los puntos discretos $n = [0, 1, 2, ..., 10]$ para obtener $y_1[n] = \cos(n)$.

c) Grafique la versión discreta usando stem plot.

In [34]:
# Solución:
# a) Señal continua cos(t)
import numpy as np
t = symbols('t')
y = cos(t)

tvals = np.linspace(0,10,1000)

yfun = lambdify(t,y,'numpy') 
yvals = yfun(tvals)

fig = go.Figure()
fig.add_trace(go.Scatter(
    x=tvals, y=yvals,
    mode='lines',
    line=dict(color='cyan', width=2),
    name=f'y(t)={y}'
))
fig.update_layout(
    title='Señal coseno continua',
    xaxis_title='t',
    yaxis_title='$cos(t)$',
    template='plotly_dark'
)

fig.show()


# b) Versión discreta cos(n)
t_disc = np.linspace(0,10,11)

yvals_disc = yfun(t_disc)

fig1 = go.Figure()
fig1.add_trace(go.Scatter(
    x=t_disc, y=yvals_disc,
    mode='lines+markers',
    line=dict(color='lime', width=2),
    marker=dict(size=10),
    name=f'y(t)={y}'
))
fig1.update_layout(
    title='Señal coseno discreta',
    xaxis_title='t',
    yaxis_title='$cos[t]$',
    template='plotly_dark'
)

fig1.show()

# c) Stem plot de la señal discreta
fig2 = go.Figure()
fig2.add_trace(go.Scatter(
    x=t_disc, y=yvals_disc,
    mode='markers',
    marker=dict(color='#ff2785', size=10),
    name=f'y[t]={y}'
))

for ti, yi in zip(t_disc, yvals_disc):
    fig2.add_shape(
        type='line',
        x0=ti, y0=0, x1=ti, y1=yi,
        line=dict(color='#ff2785', width=2)
    )

fig2.update_layout(
    title='Señal coseno discreta',
    xaxis_title='t',
    yaxis_title='$cos[t]$',
    template='plotly_dark'
)

fig2.show()

Pregunta 4: Suma de señales sinusoidales¶

a) Defina la señal $x(t) = \cos(t) + \sin(3t)$.

b) Grafique esta señal en el intervalo $[0, 20]$.

In [38]:
# Solución:
# a) Definir x(t) = cos(t) + sin(3t)
t = symbols('t')
x1 = cos(t)
x2 = sin(3*t)

x = x1 + x2

# b) Graficar en [0, 20]
tvals = np.linspace(0, 20, 2000)
xfun = lambdify(t, x, 'numpy')
xvals = xfun(tvals)

fig = go.Figure()
fig.add_trace(go.Scatter(
    x=tvals, y=xvals,
    mode='lines',
    line=dict(color="#FBFF13", width=2),
    name=f'x(t) = {x}'
))
fig.update_layout(
    title='Suma sinuoidal',
    xaxis_title='t',
    yaxis_title='$cos(t)+sin(3t)$',
    template='plotly_dark'
)
fig.show()

Pregunta 5: Modulación de amplitud¶

a) Defina la señal modulada $x(t) = \cos(100t) \cdot e^{2t}$.

b) Grafique esta señal en el intervalo $[0, 2]$.

In [41]:
# Solución:
# a) Definir señal modulada
t = symbols('t')
x = cos(100*t) * exp(2*t)

# b) Graficar en [0, 2]
tvals = np.linspace(0,2,200)
xfun = lambdify(t, x, 'numpy')
xvals = xfun(tvals)

fig = go.Figure()
fig.add_trace(go.Scatter(
    x=tvals, y=xvals,
    mode='lines',
    line=dict(color="#FF2626", width=2),
    name=f'x(t) = {x}'
))
fig.update_layout(
    title='Señal modulada',
    xaxis_title='t',
    yaxis_title=f'${sp.latex(x)}$',
    template='plotly_dark'
)
fig.show()

Pregunta 6: Señales complejas¶

a) Defina la señal compleja $y(t) = 2e^{j(\pi t + \pi/3)}$.

b) Extraiga las partes real e imaginaria de esta señal.

c) Grafique ambas partes por separado en el intervalo $[0, 2]$ con leyendas apropiadas.

In [90]:
# Solución:
# a) Definir señal compleja
t = symbols('t', real=True)
y = 2*exp(I*(pi*t+(pi/3)))

# b) Extraer partes real e imaginaria
im = sp.im(y)
real = sp.re(y)

# print(sp.latex(real))

# c) Graficar ambas partes
tvals = np.linspace(0, 2, 1000)

imfun = lambdify(t, im, 'numpy')
realfun = lambdify(t, real, 'numpy')

imvals = imfun(tvals)
realsvals = realfun(tvals)

fig1 = go.Figure()
fig1.add_trace(go.Scatter(
    x=tvals, y=realsvals,
    mode='lines',
    line=dict(color="#0EFFFF", width=2),
    name=f'Re({y})={real}'
))
fig1.update_layout(
    title='Parte real de la función',
    xaxis_title='t',
    yaxis_title='Re(y(t))',
    template='plotly_dark'
)
fig1.show()


fig2 = go.Figure()
fig2.add_trace(go.Scatter(
    x=tvals, y=imvals,
    mode='lines',
    line=dict(color="#FF0E9B", width=2),
    name=f'Im({y})={im}'
))
fig2.update_layout(
    title='Parte imaginaria de la función',
    xaxis_title='t',
    yaxis_title='Im(y(t))',
    template='plotly_dark'
)
fig2.show()

Parte II: Funciones de encendido¶

Pregunta 7: Función escalón de Heaviside¶

a) Defina simbólicamente la función escalón unitario $u(t) = \text{heaviside}(t)$.

b) Grafique esta función en el intervalo $[-5, 10]$ con límites en $y$ de $[-0.5, 1.5]$.

c) ¿Cuál es el valor de $\text{heaviside}(0)$?

d) Evalúe la función de Heaviside en los puntos discretos $n = [-5, -4, ..., 10]$ y grafique usando stem plot.

In [97]:
# Solución:
# a) Definir función Heaviside
t = symbols('t')
u = Heaviside(t)

# b) Gráfica continua
tvals = np.linspace(-5,10,1000)
ufun = lambdify(t, u, 'numpy')
uvals = ufun(tvals)

fig = go.Figure()

fig.add_trace(go.Scatter(
    x=tvals, y=uvals,
    mode='lines',
    line=dict(color='lime', width=2),
    name='u(t)'
))

fig.update_yaxes(range=[-0.5,1.5])

fig.update_layout(
    title='Función escalon',
    xaxis_title='t',
    yaxis_title='$u(t)$',
    template='plotly_dark'
)
fig.show()

# c) Valor en t=0

print(f"u(0) = {ufun(0)}")

# d) Versión discreta con stem
n = np.arange(-5,11)
uvals_dic = ufun(n)

fig = go.Figure()
fig.add_trace(go.Scatter(
    x=n, y=uvals_dic,
    mode='markers',
    marker=dict(color='cyan', size=10),
    name='u[t]'
))

for ni, ui in zip(n,uvals_dic):
    fig.add_shape(
        x0=ni, x1=ni, y0=0, y1=ui,
        type='line',
        line=dict(color='cyan', width=2)
    )

fig.update_layout(
    title='Heaviside discreto',
    xaxis_title='n',
    yaxis_title='u[t]',
    template='plotly_dark'
)
fig.update_yaxes(range=[-0.5,1.5])
fig.show()
u(0) = 0.5

Pregunta 8: Función rampa¶

a) Defina la función rampa como $r(t) = t \cdot \text{heaviside}(t)$.

b) Grafique esta función en el intervalo $[-5, 10]$.

In [98]:
# Solución:
# a) Definir función rampa
t = symbols('t')
r = t * Heaviside(t)

# b) Graficar
tvals = np.linspace(-5,10,1000)
rfun = lambdify(t, r, 'numpy')
rvals = rfun(tvals)

fig = go.Figure()

fig.add_trace(go.Scatter(
    x=tvals, y=rvals,
    mode='lines',
    line=dict(color="#fff01d", width=2),
    name=f'r(t) = {r}'
))

fig.update_layout(
    title='Función rampa',
    xaxis_title='t',
    yaxis_title='$r(t)$',
    template='plotly_dark'
)
fig.show()

Pregunta 9: Pulso rectangular¶

a) Defina un pulso rectangular de duración $T = 2$ centrado en el origen usando: $$p_T(t) = \text{heaviside}(t + T/2) - \text{heaviside}(t - T/2)$$

b) Grafique este pulso en el intervalo $[-5, 10]$ con límites en $y$ de $[-0.5, 1.5]$.

In [99]:
# Solución:
# a) Definir pulso rectangular
t = symbols('t')
T = 2
pT = Heaviside(t + (T/2)) - Heaviside(t-(T/2))

# b) Graficar
tvals = np.linspace(-5,10,1000)
pTfun = lambdify(t, pT, 'numpy')
pTvals = pTfun(tvals)

fig = go.Figure()

fig.add_trace(go.Scatter(
    x=tvals, y=pTvals,
    mode='lines',
    line=dict(color='cyan', width=2),
    name='pT(t)'
))

fig.update_yaxes(range=[-0.5,1.5])

fig.update_layout(
    title='Pulso rectangular de duración T=2',
    xaxis_title='t',
    yaxis_title='$pT(t)$',
    template='plotly_dark'
)
fig.show()

Parte III: Transformaciones de señales¶

Pregunta 10: Operaciones sobre señales¶

Considere la señal base $x(t) = t e^{-t}$.

a) Grafique la señal original en el intervalo $[-3, 3]$ con límites en $y$ de $[-3, 0.5]$.

b) Calcule y grafique la señal reflejada: $x_{\text{reflex}}(t) = x(-t)$.

c) Calcule y grafique la señal trasladada: $x_{\text{tras}}(t) = x(t-2)$.

d) Calcule y grafique la señal ensanchada: $x_{\text{broad}}(t) = x(t/3)$.

In [13]:
# Solución:
# a) Señal original x(t) = t*exp(-t)
t = symbols('t')
x = t * exp(-t)

tvals = np.linspace(-3,3,1000)
xfun = lambdify(t, x, 'numpy')
xvals = xfun(tvals)

fig = go.Figure()

fig.add_trace(go.Scatter(
    x=tvals, y=xvals,
    mode='lines',
    line=dict(color='lime', width=2),
    name='x(t)'
))

fig.update_yaxes(range=[-3,0.5])

fig.update_layout(
    title=f'Señal {x}',
    xaxis_title='t',
    yaxis_title='x(t)',
    template='plotly_dark'
)
fig.show()

# b) Reflexión: x(-t)
x_ref = x.subs(t, -t)
xfun_ref = lambdify(t, x_ref, 'numpy')
xvals_ref = xfun_ref(tvals)

fig1 = go.Figure()

fig1.add_trace(go.Scatter(
    x=tvals, y=xvals_ref,
    mode='lines',
    line=dict(color='lime', width=2),
    name='x(-t)'
))

fig1.update_yaxes(range=[-3,0.5])

fig1.update_layout(
    title=f'Señal reflejada ({x_ref})',
    xaxis_title='t',
    yaxis_title='x(-t)',
    template='plotly_dark'
)
fig1.show()

# c) Traslación: x(t-2)
x_trans = x.subs(t, t-2)
xfun_trans = lambdify(t, x_trans, 'numpy')
xvals_trans = xfun_trans(tvals)

fig2 = go.Figure()

fig2.add_trace(go.Scatter(
    x=tvals, y=xvals_trans,
    mode='lines',
    line=dict(color='lime', width=2),
    name='x(t-2)'
))

fig2.update_yaxes(range=[-3,0.5])

fig2.update_layout(
    title=f'Señal transladada ({x_trans})',
    xaxis_title='t',
    yaxis_title='x(t-2)',
    template='plotly_dark'
)
fig2.show()

# d) Ensanchamiento: x(t/3)
x_ensancha = x.subs(t, t/3)
xfun_ensancha = lambdify(t, x_ensancha, 'numpy')
xvals_ensancha = xfun_ensancha(tvals)

fig3 = go.Figure()

fig3.add_trace(go.Scatter(
    x=tvals, y=xvals_ensancha,
    mode='lines',
    line=dict(color='lime', width=2),
    name='x(t/3)'
))

fig3.update_yaxes(range=[-3,0.5])

fig3.update_layout(
    title=f'Señal ensanchada ({x_ensancha})',
    xaxis_title='t',
    yaxis_title='x(t/3)',
    template='plotly_dark'
)
fig3.show()

Pregunta 11: Descomposición par e impar¶

Toda señal se puede descomponer en una parte par y una parte impar.

a) Para la señal $x(t) = t e^{-t}$ y su reflexión $x_{\text{reflex}}(t)$, calcule:

  • Parte par: $x_e(t) = \frac{1}{2}[x(t) + x_{\text{reflex}}(t)]$
  • Parte impar: $x_o(t) = \frac{1}{2}[x(t) - x_{\text{reflex}}(t)]$

b) Grafique las tres señales ($x_e(t)$, $x_o(t)$, $x(t)$) en el mismo plot en el intervalo $[-10, 10]$ con límites en $y$ de $[-10, 10]$.

c) Verifique que $x(t) = x_e(t) + x_o(t)$.

In [27]:
# Solución:
# a) Calcular partes par e impar
t = symbols('t')

x = t * exp(-t)
x_ref = x.subs(t, -t)

x_par = 1/2 * (x + x_ref)
x_impar = 1/2 * (x - x_ref)

# b) Graficar las tres señales
tvals = np.linspace(-10, 10, 1000)

xvals = lambdify(t, x, 'numpy')(tvals)
x_par_vals = lambdify(t, x_par, 'numpy')(tvals)
x_impar_vals = lambdify(t, x_impar, 'numpy')(tvals)

fig = go.Figure()

fig.add_trace(go.Scatter(
    x=tvals, y=xvals,
    mode='lines',
    line=dict(color="#d60aff"),
    name=f'x(t) = {x}'
    ))

fig.add_trace(go.Scatter(
    x=tvals, y=x_par_vals,
    mode='lines',
    line=dict(color="#0ae2ff"),
    name=f'xpar(t) = {x_par}'
    ))

fig.add_trace(go.Scatter(
    x=tvals, y=x_impar_vals,
    mode='lines',
    line=dict(color="#ff8513"),
    name=f'ximpar(t) = {x_impar}'
    ))

fig.update_yaxes(range=[-10,10])

fig.update_layout(
    title='Descomposición de una señal en parte par e impar',
    xaxis_title='t',
    yaxis_title='Valor de las señales',
    template = 'plotly_dark'
)

fig.show()


# c) Verificar descomposición
suma = x_par + x_impar

suma_vals = lambdify(t, suma, 'numpy')(tvals)

fig1 = go.Figure()
fig1.add_trace(go.Scatter(
    x=tvals, y=xvals,
    mode='lines',
    line=dict(color="#d60aff", width=2),
    name=f'x(t)={x}'
))
fig1.add_trace(go.Scatter(
    x=tvals, y=suma_vals,
    mode='lines',
    line=dict(color="#fbff0a", width=2, dash='dash'),
    name=f'x_par(t) + x_impar'
))
fig1.update_yaxes(range=[-10,10])
fig1.update_layout(
    title='Verificación de la descomposición',
    xaxis_title='t',
    yaxis_title='Valor de las señales',
    template='plotly_dark'
)
fig1.show()

Parte IV: Cálculos de energía y potencia¶

Pregunta 12: Cálculo de RMS de función seno¶

Para una señal sinusoidal $x(t) = \sin(t)$ con período fundamental $T = 2\pi$:

a) Calcule la energía en un período: $$E = \int_0^T x^2(t) \, dt = \int_0^{2\pi} \sin^2(t) \, dt$$

b) Calcule la potencia promedio: $$P = \frac{E}{T} = \frac{E}{2\pi}$$ $$(T = 2\pi)$$

c) Calcule el valor RMS (Root Mean Square): $$\text{RMS} = \sqrt{P}$$

d) Exprese el resultado numéricamente usando aritmética simbólica.

e) Puntos extra si hacen el cálculo de la integral a mano y sacan el valor numérico

In [ ]:
# Solución:
# a) Cálculo de energía E
t = symbols('t')
x = sin(t)
T = 2*pi

E = integrate(x**2, (t, 0, T))

# b) Cálculo de potencia P
P = E/T

# c) Cálculo de RMS
RMS = sqrt(P)

# d) Evaluación numérica
print(f'E = {E}')
print(f'P = {P}')
print(f'RMS = {RMS}')
E = pi
P = 1/2
RMS = sqrt(2)/2